import 'terms.dart';

/// 特殊术语判定
String judgeSpecialTerms(Board board, ChessStep chessStep) {
  printInfo('特殊术语判定');
  var step = chessStep.toGtp();
  Terms terms = Terms.none;
  for (var entry in specialDots.entries) {
    if (entry.value.contains(step)) {
      switch (entry.key) {
        case 'threeThree':
          terms = Terms.threeThree;
        case 'starPoint':
          terms = Terms.starPoint;
        case 'smallEye':
          terms = Terms.smallEye;
        case 'outsideEye':
          terms = Terms.outsideEye;
        case 'highPoint':
          terms = Terms.highPoint;
        case 'superOutsideEye':
          terms = Terms.superOutsideEye;
        case 'superHighPoint':
          terms = Terms.superHighPoint;
        case 'tYuan':
          terms = Terms.tYuan;
      }
    }
  }
  var tempDesc = terms.desc.isNotEmpty ? '(${terms.desc})' : '';
  // printInfo('tempDesc:$tempDesc');
  if (judgeFromAbstractDirection(board, chessStep) !=
          AbstractDirection.specialDot &&
      judgeFromAbstractDirection(board, chessStep) !=
          AbstractDirection.middle) {
    /// 分投
    bool judgeSplit({int type = 0}) {
      bool area4HaveChess = false;
      bool area8HaveChessUp = false;
      bool area8HaveChessDown = false;

      /// 判断当前手的2边是否同时有子
      judgeArea8HaveChess(ChessStep step) {
        if ((changedX(chessStep) - step.x).abs() <= 1) {
          if (step.y > changedY(chessStep)) {
            area8HaveChessUp = true;
          } else if (step.y < changedY(chessStep)) {
            area8HaveChessDown = true;
          }
        } else if ((changedY(chessStep) - step.y).abs() <= 1) {
          if (step.x > changedX(chessStep)) {
            area8HaveChessUp = true;
          } else if (step.x < changedX(chessStep)) {
            area8HaveChessDown = true;
          }
        }
      }

      ChessStep? step8;
      List nonZeroSteps = getNonZeroChessSteps(board);
      nonZeroSteps.remove(chessStep);
      for (final step in nonZeroSteps) {
        final distance = distanceSquared(chessStep, step.x, step.y);
        if (distance > 0) {
          if (distance < 17) {
            area4HaveChess = true;
          }

          if (distance < 65) {
            printInfo('distance:$distance');
            step8 = step;
            if (type == 0) {
              if (step8!.bw != chessStep.bw) {
                judgeArea8HaveChess(step);
              }
            } else {
              if (step8!.bw == chessStep.bw) {
                judgeArea8HaveChess(step);
              }
            }
          }
        }
      }

      // printInfo('area4HaveChess:$area4HaveChess');
      // printInfo('area8HaveChessUp:$area8HaveChessUp');
      // printInfo('area8HaveChessDown:$area8HaveChessDown');

      if (!area4HaveChess && area8HaveChessUp && area8HaveChessDown) {
        return true;
      }
      return false;
    }

    bool isDoubleStrike(List<ChessStep> stepList) {
      for (var it in stepList) {
        List stepList3 = sCount(board, it, 4, false);
        int count3 = stepList3.length;
        if (count3 > 0) {
          var step3 = stepList3.first;
          if (changedX(step3) == chessStep.x &&
              changedY(step3) == chessStep.y) {
            return false;
          }
          if (step3.bw == chessStep.bw) {
            return true;
          }
        }
        List<ChessStep> stepList13 = sCount(board, it, 5, false);
        int count13 = stepList13.length;

        printInfo('s3:$count3');

        if (count13 > 0) {
          var step13 = stepList13.first;
          if (changedX(step13) == chessStep.x &&
              changedY(step13) == chessStep.y) {
            return false;
          }
          if (step13.bw == chessStep.bw) {
            return true;
          }
        }
      }
      return false;
    }

    if (isThreeOrFourLine(chessStep)) {
      printInfo('同时满足三四线');

      /// 同时满足三、四线，所有坐标不满足一、二线
      if (!isOneOrTwoLine(chessStep)) {
        /// 拆边（ 拆—）
        List s6List = sCount(board, chessStep, 4, true);
        if (s6List.isNotEmpty) {
          var coordinate6 = s6List.first;
          if (isThreeOrFourLine(coordinate6!) && !isOneOrTwoLine(coordinate6)) {
            return Terms.trimEdgeTrimOne.desc + tempDesc;
          }
        }

        /// 拆边（飞拆）
        List s7List = sCount(board, chessStep, 5, true);
        if (s7List.isNotEmpty) {
          var coordinate7 = s7List.first;
          if (isThreeOrFourLine(coordinate7!) && !isOneOrTwoLine(coordinate7)) {
            return Terms.trimEdgeFlyTrim.desc + tempDesc;
          }
        }

        /// 拆边（拆二）
        List s9List = sCount(board, chessStep, 9, true);
        if (s9List.isNotEmpty) {
          var coordinate9 = s9List.first;
          if (isThreeOrFourLine(coordinate9!) && !isOneOrTwoLine(coordinate9)) {
            return Terms.trimEdgeTrimTwo.desc + tempDesc;
          }
        }

        /// 拆边（大飞拆）
        List s10List = sCount(board, chessStep, 10, true);
        if (s10List.isNotEmpty) {
          var coordinate10 = s10List.first;
          if (isThreeOrFourLine(coordinate10!) &&
              !isOneOrTwoLine(coordinate10)) {
            return Terms.trimEdgeBigFlyTrim.desc + tempDesc;
          }
        }

        List<ChessStep> s3List = sCount(board, chessStep, 4, false);
        if (s3List.isNotEmpty) {
          if (isTwoLineFromStep(chessStep)) {
            if (s3Dots.contains(chessStep.toGtp())) {
              return Terms.leakTwoFourInvadeSplit.desc + tempDesc;
            } else {
              return Terms.leak.desc + tempDesc;
            }
          } else {
            if (isThreeLineFromStep(chessStep)) {
              printInfo('进入s3的判定');
              if (isDoubleStrike(s3List)) {
                return Terms.doubleStrikeOneLowStrike.desc + tempDesc;
              }
            } else if (isFourLineFromStep(chessStep)) {
              /// 找到S3的子前2/前2拐1有己方子： 夹击（—间高夹）
              if (isDoubleStrike(s3List)) {
                return Terms.doubleStrikeOneHighStrike.desc + tempDesc;
              }
            } else {
              return Terms.block.desc + tempDesc;
            }
          }
        }

        List s13List = sCount(board, chessStep, 5, false);
        if (s13List.isNotEmpty) {
          if (isTwoLineFromStep(chessStep)) {
            if (s13Dots.contains(chessStep.toGtp())) {
              return Terms.leakTwoFiveInvadeSplit.desc + tempDesc;
            } else {
              return Terms.leak.desc + tempDesc;
            }
          } else {
            return Terms.block.desc + tempDesc;
          }
        }
      }

      int s11 = sCount(board, chessStep, 16, true).length;
      if (s11 > 0) {
        /// 拆边（低拆三）
        if (isThreeLineFromStep(chessStep)) {
          return Terms.trimEdgeLowTrimThree.desc + tempDesc;
        }

        /// 拆边（高拆三）
        else if (isFourLineFromStep(chessStep)) {
          return Terms.trimEdgeHighTrimThree.desc + tempDesc;
        }
      }

      int s12 = sCount(board, chessStep, 17, true).length;
      if (s12 > 0) {
        /// 拆边（低拆三）
        if (isThreeLineFromStep(chessStep)) {
          return Terms.trimEdgeLowTrimThree.desc + tempDesc;
        }

        /// 拆边（高拆三）
        else if (isFourLineFromStep(chessStep)) {
          return Terms.trimEdgeHighTrimThree.desc + tempDesc;
        }
      }

      List<ChessStep> s14List = sCount(board, chessStep, 9, false);
      if (s14List.isNotEmpty) {
        if (isTwoLineFromStep(chessStep)) {
          return Terms.leak.desc;
        } else if (isThreeLineFromStep(chessStep)) {
          /// 找到S14的子前2/前2拐1有己方子， 夹击（ 二间低夹）
          if (isDoubleStrike(s14List)) {
            return Terms.doubleStrikeTwoLowStrike.desc + tempDesc;
          }
        } else if (isFourLineFromStep(chessStep)) {
          /// 找到S14的子前2/前2拐1有己方子， 夹击（ 二间高夹）
          if (isDoubleStrike(s14List)) {
            return Terms.doubleStrikeTwoLowStrike.desc + tempDesc;
          }
        } else {
          return Terms.block.desc + tempDesc;
        }
      }

      int s15 = sCount(board, chessStep, 10, false).length;
      if (s15 > 0) {
        return Terms.block.desc + tempDesc;
      }

      List<ChessStep> s16List = sCount(board, chessStep, 6, false);
      if (s16List.isNotEmpty) {
        if (isThreeLineFromStep(chessStep)) {
          /// 找到S16的子前2/前2拐1有己方子， 夹击（ 三间低夹）
          if (isDoubleStrike(s16List)) {
            return Terms.doubleStrikeThreeLowStrike.desc + tempDesc;
          }
        } else if (isFourLineFromStep(chessStep)) {
          /// 找到S16的子前2/前2拐1有己方子， 夹击（ 三间高夹）
          if (isDoubleStrike(s16List)) {
            return Terms.doubleStrikeThreeHighStrike.desc + tempDesc;
          }
        } else {
          return Terms.split.desc + tempDesc;
        }
      }

      List<ChessStep> s17List = sCount(board, chessStep, 17, false);
      if (s17List.isNotEmpty) {
        if (isThreeLineFromStep(chessStep)) {
          /// 找到S17的子前2/前2拐1有己方子， 夹击（三间低夹）
          if (isDoubleStrike(s17List)) {
            return Terms.doubleStrikeThreeLowStrike.desc + tempDesc;
          }
        } else if (isFourLineFromStep(chessStep)) {
          /// 找到S17的子前2/前2拐1有己方子， 夹击（三间高夹）
          if (isDoubleStrike(s17List)) {
            return Terms.doubleStrikeThreeHighStrike.desc + tempDesc;
          }
        } else {
          /// 分投
          return Terms.split.desc + tempDesc;
        }
      }

      /// 分投
      if (judgeSplit()) {
        return Terms.split.desc + tempDesc;
      }
      if (judgeSplit(type: 1)) {
        return Terms.trimEdge.desc + tempDesc;
      }
    } else {
      List<ChessStep> s3List = sCount(board, chessStep, 3, true);

      List<ChessStep> s13List = sCount(board, chessStep, 13, true);
      List<ChessStep> s14List = sCount(board, chessStep, 14, true);

      final bool isCurrentStepTwoLine = isTwoLineFromStep(chessStep);
      final bool isS3FirstStepTwoLine =
          s3List.isNotEmpty && isTwoLineFromStep(s3List.first);
      final bool isS13FirstStepTwoLine =
          s13List.isNotEmpty && isTwoLineFromStep(s13List.first);
      final bool isS14FirstStepTwoLine =
          s14List.isNotEmpty && isTwoLineFromStep(s14List.first);

      if (isCurrentStepTwoLine ||
          isS3FirstStepTwoLine ||
          isS13FirstStepTwoLine ||
          isS14FirstStepTwoLine) {
        if (s3List.isNotEmpty && isThreeOrFourLine(s3List.first)) {
          if (s3Dots.contains(s3List.first.toGtp())) {
            return Terms.leakTwoFourInvadeSplit.desc + tempDesc;
          } else {
            return Terms.leak.desc + tempDesc;
          }
        }
      }
    }
  }
  if (terms == Terms.none) {
    terms = Terms.chess;
  }
  return terms.desc;
}
